/*
* This file is a part of the open-eBackup project.
* This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
* If a copy of the MPL was not distributed with this file, You can obtain one at
* http://mozilla.org/MPL/2.0/.
*
* Copyright (c) [2024] Huawei Technologies Co.,Ltd.
*
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
*/
#include "gtest/gtest.h"
#include "gmock/gmock.h"
#include "stub.h"
#include "SnapshotDelete.h"
#include "ClientInvoke.h"
#include "SnapshotCommon.h"
#include "PluginUtilities.h"

using ::testing::_;
using testing::AllOf;
using ::testing::AnyNumber;
using ::testing::AtLeast;
using testing::ByMove;
using testing::DoAll;
using ::testing::Eq;
using ::testing::Field;
using ::testing::Ge;
using ::testing::Gt;
using testing::InitGoogleMock;
using ::testing::Invoke;
using ::testing::Ne;
using ::testing::Return;
using ::testing::Sequence;
using ::testing::SetArgReferee;
using ::testing::SetArgumentPointee;
using ::testing::Throw;
using namespace std;
using namespace Module;

class SnapshotDeleteTest : public testing::Test {
public:
    Stub stub;
    unique_ptr<SnapshotDelete> m_SnapshotDelete;
    void SetUp();
    void TearDown();
    static void SetUpTestCase();
    static void TearDownTestCase();
};

static AppProtect::DelCopyJob DelCopyJobSetup()
{
    AppProtect::DelCopyJob delCopyJob;
    delCopyJob.requestId = "123456789";
    delCopyJob.jobId = "111111";
    delCopyJob.protectEnv.id = "123";
    delCopyJob.protectEnv.name = "123";
    delCopyJob.protectEnv.port = 8088;
    delCopyJob.protectEnv.auth.authkey = "admin";
    delCopyJob.protectEnv.auth.authPwd = "Huawei@123456789";
    delCopyJob.protectEnv.subType = "1";
    delCopyJob.protectEnv.endpoint = "127.0.0.1";
    delCopyJob.protectObject.id = "123";
    delCopyJob.protectObject.name = "123";
    delCopyJob.protectObject.parentId = " 4564654645564";
    delCopyJob.protectObject.parentName = "test_filesystem";
    delCopyJob.protectObject.subType = "5";

    delCopyJob.protectObject.auth.authkey = "admin";
    delCopyJob.protectObject.auth.authPwd = "Huawei@123456789";
    delCopyJob.protectObject.extendInfo = "{\"authMode\":\"1\",\"filters\":\"\",\"ip\":\"10.28.12.144\""
        ",\"kerberosId\":\"0\",\"shareMode\":\"1\"}";

    Copy copy;
    copy.extendInfo = "{\"authMode\":\"1\",\"filters\":\"\",\"ip\":\"10.28.12.144\""
        ",\"kerberosId\":\"0\",\"shareMode\":\"1\", \"extendInfo\":{\"snapshotId\":\"cgdhshgchg\"}}";
    delCopyJob.copies.push_back(copy);
    return delCopyJob;
}

static SubJob CreateSubJob()
{
    SubJob subJob;
    subJob.jobId = "jobId123";
    subJob.subJobId = "subJob123";
    subJob.jobName = "XYZ";
    subJob.jobPriority = 1;
    subJob.jobInfo = "{\"ControlFile\":\"\",\"SubTaskType\":1,\"Ext\":\"\"}";
    return subJob;
}

void SnapshotDeleteTest::SetUp()
{
    m_SnapshotDelete = std::make_unique<SnapshotDelete>();
    m_SnapshotDelete->m_jobCommonInfo =
        std::make_unique<JobCommonInfo>(std::make_shared<AppProtect::DelCopyJob>(DelCopyJobSetup()));
}

void SnapshotDeleteTest::TearDown() {}

void SnapshotDeleteTest::SetUpTestCase() {}

void SnapshotDeleteTest::TearDownTestCase() {}

static void ReportJobDetails_Stub(void *obj)
{
    return;
}

static void AddNewJob_Stub_Fail(ActionResult returnValue, const std::vector<SubJob> &job)
{
    returnValue.code = Module::FAILED;
    return;
}

static void AddNewJob_Stub_Succ(void *obj)
{
    return;
}

static int UpdateDeviceAvilableIP_Stub(void *obj)
{
    return Module::SUCCESS;
}

static int DeleteSnapshotWithVstoreId_Stub_Succ(void *obj)
{
    return Module::SUCCESS;
}

static int DeleteSnapshotWithVstoreId_Stub_Fail(void *obj)
{
    return Module::FAILED;
}

static std::string GetDeployType_stub_secure_machine()
{
    cout << "Enter GetDeployType_stub_secure_machine" << endl;
    return "d5";
}

static std::string GetDeployType_stub_anti_ransomware()
{
    cout << "Enter GetDeployType_stub_anti_ransomware" << endl;
    return "d4";
}

/*
 * 用例名称：GenerateSubJob_Suc
 * 前置条件：无
 * check点：准备前置任务
 */
TEST_F(SnapshotDeleteTest, PrerequisiteJob)
{
    stub.set(PluginUtils::GetDeployType, GetDeployType_stub_anti_ransomware);
    m_SnapshotDelete->PrerequisiteJob();
    EXPECT_EQ(0, 0);
    stub.reset(PluginUtils::GetDeployType);
}

/*
 * 用例名称：GenerateSubJob_Suc
 * 前置条件：无
 * check点：post任务
 */
TEST_F(SnapshotDeleteTest, PostJob)
{
    stub.set(PluginUtils::GetDeployType, GetDeployType_stub_anti_ransomware);
    m_SnapshotDelete->PostJob();
    EXPECT_EQ(0, 0);
    stub.reset(PluginUtils::GetDeployType);
}

/*
 * 用例名称：GenerateSubJob_Suc
 * 前置条件：无
 * check点：生成子任务成功
 */
TEST_F(SnapshotDeleteTest, GenerateSubJob_Suc)
{
    stub.set(ADDR(JobService, AddNewJob), AddNewJob_Stub_Succ);
    stub.set(ADDR(JobService, ReportJobDetails), ReportJobDetails_Stub);
    stub.set(PluginUtils::GetDeployType, GetDeployType_stub_anti_ransomware);

    EXPECT_EQ(m_SnapshotDelete->GenerateSubJob(), Module::SUCCESS);

    stub.reset(ADDR(JobService, AddNewJob));
    stub.reset(ADDR(JobService, ReportJobDetails));
    stub.reset(PluginUtils::GetDeployType);
}

/*
 * 用例名称：GenerateSubJob_Suc
 * 前置条件：无
 * check点：生成子任务失败
 */
TEST_F(SnapshotDeleteTest, GenerateSubJob_Fail)
{
    stub.set(ADDR(JobService, AddNewJob), AddNewJob_Stub_Fail);
    stub.set(ADDR(JobService, ReportJobDetails), ReportJobDetails_Stub);
    stub.set(PluginUtils::GetDeployType, GetDeployType_stub_anti_ransomware);

    EXPECT_EQ(m_SnapshotDelete->GenerateSubJob(), Module::FAILED);

    stub.reset(ADDR(JobService, AddNewJob));
    stub.reset(ADDR(JobService, ReportJobDetails));
    stub.reset(PluginUtils::GetDeployType);
}

/*
 * 用例名称：GenerateSubJob_Suc
 * 前置条件：无
 * check点：执行子任务
 */
TEST_F(SnapshotDeleteTest, ExecuteSubJob)
{
    std::shared_ptr<SubJob> subJobptr = std::make_shared<SubJob>(CreateSubJob());
    m_SnapshotDelete->SetSubJob(subJobptr);

    stub.set(ADDR(JobService, AddNewJob), AddNewJob_Stub_Succ);
    stub.set(ADDR(JobService, ReportJobDetails), ReportJobDetails_Stub);
    stub.set((int(DoradoNas::*)(mp_string SnapshotName, mp_string id))ADDR(DoradoNas, DeleteSnapshotWithVstoreId),
                DeleteSnapshotWithVstoreId_Stub_Succ);
    stub.set(PluginUtils::GetDeployType, GetDeployType_stub_anti_ransomware);

    EXPECT_EQ(m_SnapshotDelete->ExecuteSubJob(), Module::SUCCESS);

    stub.set((int(DoradoNas::*)(mp_string SnapshotName, mp_string id))ADDR(DoradoNas, DeleteSnapshotWithVstoreId),
                DeleteSnapshotWithVstoreId_Stub_Fail);

    EXPECT_EQ(m_SnapshotDelete->ExecuteSubJob(), Module::FAILED);

    // 设置extendInfo为空，JsonHelper::JsonStringToStruct返回false，走异常流程
    m_SnapshotDelete->GenerateSubJob();
    std::shared_ptr<DelCopyJob> jobInfoPtr =
        dynamic_pointer_cast<DelCopyJob>(m_SnapshotDelete->m_jobCommonInfo->GetJobInfo());
    jobInfoPtr->protectObject.extendInfo = "";
    EXPECT_EQ(m_SnapshotDelete->ExecuteSubJob(), Module::FAILED);

    stub.reset(ADDR(JobService, AddNewJob));
    stub.reset(ADDR(JobService, ReportJobDetails));
    stub.reset((int(DoradoNas::*)(mp_string SnapshotName, mp_string id))ADDR(DoradoNas, DeleteSnapshotWithVstoreId));
    stub.reset(PluginUtils::GetDeployType);
}

TEST_F(SnapshotDeleteTest, ExecutePacificDelete)
{
    std::shared_ptr<SubJob> subJobptr = std::make_shared<SubJob>(CreateSubJob());
    m_SnapshotDelete->SetSubJob(subJobptr);

    stub.set(ADDR(JobService, AddNewJob), AddNewJob_Stub_Succ);
    stub.set(ADDR(JobService, ReportJobDetails), ReportJobDetails_Stub);
    stub.set((int(DoradoNas::*)(mp_string SnapshotName, mp_string id))ADDR(DoradoNas, DeleteSnapshotWithVstoreId),
                DeleteSnapshotWithVstoreId_Stub_Succ);
    stub.set(PluginUtils::GetDeployType, GetDeployType_stub_anti_ransomware);

    EXPECT_EQ(m_SnapshotDelete->ExecuteSubJob(), Module::SUCCESS);

    stub.set((int(DoradoNas::*)(mp_string SnapshotName, mp_string id))ADDR(DoradoNas, DeleteSnapshotWithVstoreId),
                DeleteSnapshotWithVstoreId_Stub_Fail);

    EXPECT_EQ(m_SnapshotDelete->ExecuteSubJob(), Module::FAILED);

    stub.reset(ADDR(JobService, AddNewJob));
    stub.reset(ADDR(JobService, ReportJobDetails));
    stub.reset((int(DoradoNas::*)(mp_string SnapshotName, mp_string id))ADDR(DoradoNas, DeleteSnapshotWithVstoreId));
    stub.reset(PluginUtils::GetDeployType);
}